package org.framework.common.ext.util;

import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.netease.api.post.NIMPost;
import com.netease.api.post.NIMResponse;

/**
 * 网络请求工具类
 * <p>描述: </p>
 * <p>Company: Professional</p>
 * @author chanlong(陈龙)
 * @date 2016年9月20日 下午4:06:35
 * @version 1.0.2016
 */
public class HttpClientUtil {
	
	private static Charset ENCODING = Consts.UTF_8;
	
	private static HttpClientUtil instance;

	// SSL安全套节字连接工厂
	private SSLConnectionSocketFactory factory;

	private CloseableHttpClient client;

	private HttpRequestBase request;

	/**
	 * 请求类型 
	 * <p>描述: </p>
	 * <p>Company: Professional</p>
	 * @author chanlong(陈龙)
	 * @date 2016年9月20日 下午5:14:14
	 * @version 1.0.2016
	 */
	public static enum RequestType {
		get {
			@Override
			public HttpGet get(final String url, final List<NameValuePair> params) {
				return new HttpGet(url);
			}
		},
		post {
			@Override
			public HttpPost get(final String url, final List<NameValuePair> params) {
				HttpPost post = new HttpPost(url);

				// POST请求设置参数体
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, ENCODING);
				post.setEntity(entity);

				return post;
			}
		};
		public abstract HttpRequestBase get(final String url, final List<NameValuePair> params);
	}
	
	/**
	 * 请求头类型
	 * <p>描述: </p>
	 * <p>Company: Professional</p>
	 * @author chanlong(陈龙)
	 * @date 2016年9月20日 下午4:12:57
	 * @version 1.0.2016
	 */
	public static enum ApplicationType {
		TEXT("text/xml"), XML("application/xml"), JSON("application/json"), FORM("application/x-www-form-urlencoded");

		private String type;

		private ApplicationType(String type) {
			this.type = type;
		}

		public String value() {
			return type;
		}
	}
	
	/**
	 * 创建连接客户端.
	 * @return
	 * @author chanlong(陈龙)
	 * @date 2016年9月20日 下午4:58:04
	 */
	public CloseableHttpClient createHttpClient() {
		// 开启SSL安全套节字
		enableSSL();
		
		// 获取请求配置
		RequestConfig config = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT)
													 .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
													 .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
													 .setExpectContinueEnabled(true)
													 .build();
		// 注册套节字连接工厂
		Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
																	.register("http", PlainConnectionSocketFactory.INSTANCE)
																	.register("https", factory).build();
		// 创建连接池管理器
		PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(registry);
		
		// 创建连接客户端
		return HttpClients.custom().setConnectionManager(manager).setDefaultRequestConfig(config).build();
	}
	
	/**
	 * 创建请求.
	 * @param type
	 * @param url
	 * @param params
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @author chanlong(陈龙)
	 * @date 2016年9月20日 下午5:30:32
	 */
	public static HttpClientUtil request(final RequestType type, final String url, final List<NameValuePair> params) {
		if (instance == null) instance = new HttpClientUtil(type, url, params);

		return instance;
	}
	
	/**
	 * 添加请求头.
	 * @param name
	 * @param value
	 * @author chanlong(陈龙)
	 * @date 2016年9月20日 下午5:32:08
	 */
	public HttpClientUtil addHead(final String name, final String value) {
		if (request != null) {
			request.addHeader(name, value);
		}
		return this;
	}
	
	/**
	 * 发送请求.
	 * @return
	 * @author chanlong(陈龙)
	 * @date 2016年9月20日 下午5:34:04
	 */
	public String execute(){
		try {
			CloseableHttpResponse response = client.execute(request);
			HttpEntity entity = response.getEntity();
			return EntityUtils.toString(entity, ENCODING);
		} catch (IOException e) {
			return null;
		}
	}
	
	/*
	 * 开启SSL套节字
	 */
	private void enableSSL(){
		try {
			SSLContext context = SSLContext.getInstance("TLS");
			context.init(null, new TrustManager[]{getTrustManager()}, null);
			factory = new SSLConnectionSocketFactory(context);
		} catch (NoSuchAlgorithmException | KeyManagementException e) {
			e.printStackTrace();
		}
	}
	
	/*
	 * 获取证书管理器
	 * (取消SSL证书验证)
	 */
	private TrustManager getTrustManager(){
		return new X509TrustManager() {
			
			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
			
			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				
			}
			
			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				
			}
		};
	}
	
	private HttpClientUtil(final RequestType type, final String url, final List<NameValuePair> params) {
		// 创建客户端
		client = createHttpClient();
		
		// 创建请求
		request = type.get(url, params);
	}
	
	public static void main(String[] args) throws IOException {
		String url = "https://api.netease.im/call/ecp/startcall.action";
		//String url = "https://api.netease.im/call/ecp/queryBySession.action";
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        
        // d3ef1c83-a208-47a4-9d82-f8ce3d53981f
        
        params.add(new BasicNameValuePair("callerAcc", "miwawa_0test"));
        params.add(new BasicNameValuePair("caller", "18019294516"));
        params.add(new BasicNameValuePair("callee", "18616584947"));
        params.add(new BasicNameValuePair("maxDur", String.valueOf(Integer.MAX_VALUE)));
        params.add(new BasicNameValuePair("record", "true"));
        
        //params.add(new BasicNameValuePair("session", "9b1fe433-c1df-4376-95c4-e62c7c10bcd0"));
        //params.add(new BasicNameValuePair("type", "1"));
        NIMResponse res = NIMPost.factory().postNIMServer(url, params);
        System.out.println(res.getCode());
	}
}
